// -----------------------------
// Author: 		Dhaenens Gert	
// Creation: 	12/3/2014 10:59:28 PM				
// -----------------------------

#include "WaterDisplacementGenerator.h"

#include "Application.h"
#include "RenderManager.h"
#include "Mutex.h"

#include "Noise1234.h"

#include "Filters.h"

ITexture2D* WaterDisplacementGenerator::Generate(Application* lpApp, UInt32 width, UInt32 height, Float scale)
{
	// Generate the 4 Channels
	Float* lpChannels[4];
	for (UInt32 i = 0; i < 4; ++i)
	{
		Float n = Math::Pow((Float) 2.0f, (Int32)i);
		lpChannels[i] = GenerateChannel(width, height, scale / n);
	}

	// Create the Final Output
	Float* lpData = new Float[width * height * 4];
	for (UInt32 i = 0; i < width * height; ++i)
	{
		lpData[(i * 4) + 0] = lpChannels[0][i];
		lpData[(i * 4) + 1] = lpChannels[1][i];
		lpData[(i * 4) + 2] = lpChannels[2][i];
		lpData[(i * 4) + 3] = lpChannels[3][i];
	}

	// Blur the Data
	lpData = Filters::Blur(width, height, 4, 8, lpData);

	// Create the Texture
	ITexture2D* lpTexture = ITexture2D::Create(lpApp->GetRenderer()->GetDevice(), width, height, Format::Float4, lpData);
	
	// Clean up the Data
	for (UInt32 i = 0; i < 4; ++i)
		delete[] lpChannels[i];
	delete[] lpData;

	return lpTexture;
}

Float* WaterDisplacementGenerator::GenerateChannel(UInt32 width, UInt32 height, Float scale)
{
	Float* lpData = new Float[width * height];

	// Generate a Random Offset
	for (UInt32 y = 0; y < height; ++y)
	{
		for (UInt32 x = 0; x < width; ++x)
		{
			Float px = (Float)x / width * scale;
			Float py = (Float)y / height * scale;
			Float val = Noise1234::octave_pnoise(8, 0.05f, px, py, width, height);
			val = (val + 1.0f) / 2.0f;
			lpData[(y * width) + x] = val;
		}
	}

	return lpData;
}